﻿using System.Collections.Specialized;
using System.Linq;
using System.Web.Mvc;
using System.Xml.Linq;
using NUnit.Framework;
using WB.Mvc.Forms;

namespace WB.Forms.Tests
{
	[TestFixture]
	public class ModelFormTestFixture
	{
		#region Setup/Teardown

		[SetUp]
		public void BeforeEachTest()
		{
			model = new ModelStub();
			modelForm = new ModelForm<ModelStub>(model);
			modelForm.ShouldIncludeProperty = descriptor => descriptor.Name != "Id";
		}

		#endregion

		[Test]
		public void ShouldHaveAtLeastOneFieldGroup()
		{
			Assert.Less(0, modelForm.FieldGroups.Count, "At least one field group should have been present.");
		}

		[Test]
		public void ShouldHaveDefaultActionOfEmptyString()
		{
			string defaultAction = string.Empty;

			Assert.AreEqual(defaultAction, modelForm.Action);
		}

		[Test]
		public void ShouldHaveDefaultMethodOfPost()
		{
			FormMethod defaultMethod = FormMethod.Post;

			Assert.AreEqual(defaultMethod, modelForm.Method);
		}

		[Test]
		public void ShouldHaveDefaultStrategyProvider()
		{
			Assert.IsNotNull(modelForm.FieldGroupStrategyProvider);
		}

		[Test]
		public void ShouldHaveFields()
		{
			Assert.IsNotNull(modelForm.Fields);
		}

		[Test]
		public void ShouldHaveTwoDivs()
		{
			string form = modelForm.AsDiv();

			XElement ele = XElement.Parse(form);

			Assert.AreEqual(2, ele.Descendants("div").Count());
		}

		[Test]
		public void ShouldHaveTwoFieldGroups()
		{
			var parent = new Parent();

			var modelForm = new ModelForm<Parent>(parent);
			modelForm.ShouldIncludeProperty = descriptor => descriptor.Name != "Id";

			modelForm.AsDiv();

			Assert.AreEqual(2, modelForm.FieldGroups.Count(),
			                "Should have found two field groups: one for parent and one for child.");
			Assert.AreEqual(2, modelForm.Fields.Count(), "Should have found two fields.");
		}

		[Test]
		public void ShouldHaveTwoFields()
		{
			modelForm.Load(new NameValueCollection { { "Name", "Billy" } });
			Assert.AreEqual(2, modelForm.Fields.Count());
		}

		[Test]
		public void ShouldProduceValidXmlFromAsDiv()
		{
			string form = modelForm.AsDiv();

			XElement ele = XElement.Parse(form);
		}

		[Test]
		public void ShouldUpdateModel()
		{
			var formValues = new NameValueCollection {{"Name", "model stub"}, {"IsTrue", "false"}};

			modelForm.Load(formValues);

			Assert.AreEqual("model stub", model.Name);
			Assert.IsFalse(model.IsTrue);
		}

		private ModelForm<ModelStub> modelForm;
		private ModelStub model;

		protected class ModelStub
		{
			public int Id { get; set; }

			public string Name { get; set; }

			public bool IsTrue { get; set; }
		}
	}

	public class Parent
	{
		public Parent()
		{
			Child = new Child();
		}

		public int Id { get; set; }

		public string Name { get; set; }

		public Child Child { get; set; }
	}

	public class Child
	{
		public string Name { get; set; }
	}
}